//===============================================================================
// XGenPlus Tool
// ==============================================================================
// Please visit http://www.codeplex.com/xgenplus for latest updates.
//
// This source is subject to the GNU General Public License v2.
// 
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.IO;
using System.CodeDom;
using Microsoft.CSharp;
using System.Collections;
using System.CodeDom.Compiler;
using System.Xml;
using System.Xml.Serialization;

namespace XGenPlus
{
    /// <summary>
    /// Main program class. Copyright (c) UST Global 2006-2007
    /// </summary>
    public class Program
    {
        static int Main(string[] args)
        {
            try
            {
                bool result = Init(args);

                if (result)
                {
                    System.Environment.ExitCode = 0;
                    return 0;
                }


            }
            catch (Exception e)
            {
                Console.WriteLine("Error: " + e.Message + ". Details in XgenErrorDump.log");
                try
                {
                    using (StreamWriter sw = new StreamWriter("XgenErrorDump.log"))
                    {
                        sw.Write(e.ToString());
                    }
                }
                catch { }
            }

            System.Environment.ExitCode = 1;
            return 1;


        }

        private static void WriteToConsole(string s)
        {
            Console.WriteLine(s);
        }

        /// <summary>
        /// Driver routine
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        private static bool Init(string[] args)
        {

            Logger log = new Logger();
            log.MessageListener += new Logger.MessageListenerDelegate(WriteToConsole);



            //Argument variables
            Parameters p = new Parameters();
            if (null == args || args.Length < 1) return WriteUsage("");

            //Process our arguments
            for (int i = 0; i < args.Length; i++)
            {

                string key = string.Empty;
                string value = string.Empty;

                try
                {
                    int index = args[i].IndexOf(":");
                    if (index != -1)
                    {
                        value = args[i].Substring(index + 1).Trim();
                        key = args[i].Substring(0, index).Trim();
                    }
                    else
                        key = args[i];



                    //Checking for command line arguments, and parsing the same
                    if (key == null && value == null)
                        return WriteUsage("Invalid argument - " + key);
                    else if (ArgumentHelper.ArgumentMatch(key, "assembly"))
                        p.AssemblyName = value;
                    else if (ArgumentHelper.ArgumentMatch(key, "getconfig"))
                        p.GetConfig = value;
                    else if (ArgumentHelper.ArgumentMatch(key, "putconfig"))
                        p.PutConfig = value;
                    else if (ArgumentHelper.ArgumentMatch(key, "reference"))
                    {
                        List<string> al = new List<string>();
                        ArgumentHelper.ParseList(value, al);
                        p.ReferenceList = al;
                    }
                    else if (ArgumentHelper.ArgumentMatch(key, "exclude"))
                    {
                        List<string> al = new List<string>();
                        ArgumentHelper.ParseList(value, al);
                        p.ExcludeList = al;
                    }
                    else if (ArgumentHelper.ArgumentMatch(key, "include"))
                    {
                        List<string> al = new List<string>();
                        ArgumentHelper.ParseList(value, al);
                        p.IncludeList = al;
                    }
                    else if (ArgumentHelper.ArgumentMatch(key, "from"))
                        p.From = value;
                    else if (ArgumentHelper.ArgumentMatch(key, "copyto"))
                        p.CopyTo = value;
                    else if (ArgumentHelper.ArgumentMatchEx(key, "nocompile", 3))
                        p.NoCompile = true;
                    else if (ArgumentHelper.ArgumentMatch(key, "serializeall"))
                        p.SerializeAll = true;
                    else if (ArgumentHelper.ArgumentMatchEx(key, "nogenerate", 3))
                        p.NoGenerate = true;
                    else if (value == string.Empty && (key.ToLower().EndsWith(".dll") || key.ToLower().EndsWith(".exe")))
                        p.AssemblyName = key;
                }
                catch
                {
                    return WriteUsage("Invalid argument  - " + args[i]);
                }
            }

            if (null != p.GetConfig && p.GetConfig != "")
            {
                try
                {
                    p = Config.Util.GetConfig(p.GetConfig);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Invalid config file " + p.PutConfig + "." + e.Message);
                }
            }


            if (p.AssemblyName == null) return WriteUsage("Please specify assembly name");

            bool result = XGenPlus.Generator.Runner.InvokeRunnerInOwnAppDomain(log, p);

            if (null != p.PutConfig && p.PutConfig != "")
            {
                try
                {
                    Config.Util.PutConfig(p, p.PutConfig);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Unable to save config to file " + p.PutConfig + "." + e.Message);
                }
            }

            return result;
        }

        /// <summary>
        /// Write the usage
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        private static bool WriteUsage(string msg)
        {
            Console.WriteLine();
            if (msg != null && msg != "") Console.WriteLine(msg);
            Console.WriteLine(helpString);
            Console.WriteLine("See the Readme.txt file for more explanation of switches and examples");

            return false;
        }

        private static string helpString = @"Usage: XGenPlus /assembly:assemblyname [/exclude:namespace1,namespace2] [/include:namespace1,namespace2] [/reference:assembly1,assembly2] [/copyto:path] [/nocompile] [/nogenerate] [/getconfig:filename] [/putconfig:filename] [/serializeall]";
    }
}
